/**
 * JZ UnoCSS - 文件扫描器
 * 扫描项目文件并提取类名
 * @version 1.1.0
 * @author jz
 */

/**
 * 递归扫描目录
 * @param {string} currentDir - 当前目录
 * @param {string[]} targetExtensions - 目标文件扩展名
 * @param {string[]} excludeDirs - 排除的目录
 * @returns {string[]} 文件路径数组
 */
export function scanDirectory(currentDir, targetExtensions = ['.uvue'], excludeDirs = ['node_modules', 'unpackage', '.git', 'dist']) {
    const files = [];
    
    try {
        const fs = require('fs');
        const path = require('path');
        
        if (!fs.existsSync(currentDir)) {
            console.warn(`[JZ UnoCSS] 目录不存在: ${currentDir}`);
            return files;
        }
        
        const items = fs.readdirSync(currentDir);
        
        for (const item of items) {
            // 跳过隐藏文件和目录
            if (item.startsWith('.') && !item.startsWith('.uvue')) {
                continue;
            }
            
            // 跳过排除的目录
            if (excludeDirs.includes(item)) {
                continue;
            }
            
            const itemPath = path.join(currentDir, item);
            
            try {
                const stat = fs.statSync(itemPath);
                
                if (stat.isDirectory()) {
                    // 递归扫描子目录
                    files.push(...scanDirectory(itemPath, targetExtensions, excludeDirs));
                } else if (stat.isFile()) {
                    // 检查文件扩展名
                    if (targetExtensions.some(ext => itemPath.toLowerCase().endsWith(ext))) {
                        files.push(itemPath);
                    }
                }
            } catch (statError) {
                console.warn(`[JZ UnoCSS] 无法访问 ${itemPath}:`, statError.message);
            }
        }
    } catch (error) {
        console.warn(`[JZ UnoCSS] 无法读取目录 ${currentDir}:`, error.message);
    }
    
    return files;
}

/**
 * 从文件内容中提取类名
 * @param {string} content - 文件内容
 * @returns {string[]} 类名数组
 */
export function extractClassNamesFromContent(content) {
    const classNames = new Set();
    
    try {
        // 1. 处理静态 class="..." 中的类名
        const staticClassRegex = /\bclass\s*=\s*["']([^"']+)["']/g;
        let match;
        
        while ((match = staticClassRegex.exec(content)) !== null) {
            const classString = match[1];
            const classes = classString.split(/\s+/).filter(cls => cls.trim());
            classes.forEach(cls => {
                if (cls.trim()) {
                    classNames.add(cls.trim());
                }
            });
        }
        
        // 2. 处理动态 :class="..." 中的类名
        const dynamicClassRegex = /:class\s*=\s*"([^"]+)"/g;
        const dynamicClassRegexSingle = /:class\s*=\s*'([^']+)'/g;
        
        // 处理双引号包裹的表达式
        while ((match = dynamicClassRegex.exec(content)) !== null) {
            const expression = match[1];
            
            if (!expression || !expression.trim()) {
                continue;
            }
            
            // 安全提取动态类名中的字符串字面量
            const dynamicClassNames = extractDynamicClassNames(expression);
            dynamicClassNames.forEach(cls => {
                if (cls.trim()) {
                    classNames.add(cls.trim());
                }
            });
        }
        
        // 处理单引号包裹的表达式
        while ((match = dynamicClassRegexSingle.exec(content)) !== null) {
            const expression = match[1];
            
            if (!expression || !expression.trim()) {
                continue;
            }
            
            // 安全提取动态类名中的字符串字面量
            const dynamicClassNames = extractDynamicClassNames(expression);
            dynamicClassNames.forEach(cls => {
                if (cls.trim()) {
                    classNames.add(cls.trim());
                }
            });
        }
        
        console.log(`[JZ UnoCSS] file-scanner: 提取到 ${classNames.size} 个类名（包含静态和动态）`);
        
    } catch (error) {
        console.warn('[JZ UnoCSS] file-scanner: 类名提取出错:', error.message);
    }
    
    return Array.from(classNames);
}

/**
 * 安全提取动态类名表达式中的字符串字面量
 * @param {string} expression - 动态类名表达式
 * @returns {string[]} 提取到的类名数组
 */
function extractDynamicClassNames(expression) {
    const classNames = new Set();
    
    try {
        // 预处理：去除表达式中的HTML实体编码
        const cleanExpression = expression.replace(/&quot;/g, '"').replace(/&#39;/g, "'");
        
        // 1. 提取单引号字符串字面量（使用更精确的正则）
        const singleQuoteMatches = cleanExpression.match(/'([^'\\]*(\\.[^'\\]*)*)'/g);
        if (singleQuoteMatches) {
            singleQuoteMatches.forEach(match => {
                const className = match.slice(1, -1);
                if (className && className.trim()) {
                    if (className.includes(' ')) {
                        className.split(/\s+/).forEach(cls => {
                            if (cls.trim()) classNames.add(cls.trim());
                        });
                    } else {
                        classNames.add(className.trim());
                    }
                }
            });
        }
        
        // 2. 提取双引号字符串字面量（处理嵌套情况）
        const doubleQuoteMatches = cleanExpression.match(/"([^"\\]*(\\.[^"\\]*)*)"/g);
        if (doubleQuoteMatches) {
            doubleQuoteMatches.forEach(match => {
                const className = match.slice(1, -1);
                if (className && className.trim()) {
                    if (className.includes(' ')) {
                        className.split(/\s+/).forEach(cls => {
                            if (cls.trim()) classNames.add(cls.trim());
                        });
                    } else {
                        classNames.add(className.trim());
                    }
                }
            });
        }
        
        // 3. 专门处理三元表达式中的字符串
        // 特别针对: condition ? 'class1 class2' : 'class3 class4' 这种模式
        const ternaryPattern = /\?\s*['"]([^'"]+)['"]\s*:\s*['"]([^'"]+)['"]/g;
        let ternaryMatch;
        while ((ternaryMatch = ternaryPattern.exec(cleanExpression)) !== null) {
            // 处理 ? 后面的类名
            const trueClasses = ternaryMatch[1];
            if (trueClasses && trueClasses.trim()) {
                if (trueClasses.includes(' ')) {
                    trueClasses.split(/\s+/).forEach(cls => {
                        if (cls.trim()) classNames.add(cls.trim());
                    });
                } else {
                    classNames.add(trueClasses.trim());
                }
            }
            
            // 处理 : 后面的类名
            const falseClasses = ternaryMatch[2];
            if (falseClasses && falseClasses.trim()) {
                if (falseClasses.includes(' ')) {
                    falseClasses.split(/\s+/).forEach(cls => {
                        if (cls.trim()) classNames.add(cls.trim());
                    });
                } else {
                    classNames.add(falseClasses.trim());
                }
            }
        }
        
        // 4. 提取对象键名中的类名
        const objectKeyMatches = cleanExpression.match(/['"]([^'"]+)['"]:\s*[\w.!?&|]+/g);
        if (objectKeyMatches) {
            objectKeyMatches.forEach(match => {
                const keyMatch = match.match(/['"]([^'"]+)['"]/);
                if (keyMatch && keyMatch[1]) {
                    classNames.add(keyMatch[1].trim());
                }
            });
        }
        
        // 5. 处理不带引号的对象键名
        const unquotedKeyMatches = cleanExpression.match(/\{\s*([a-zA-Z_$][a-zA-Z0-9_$-]*)\s*:/g);
        if (unquotedKeyMatches) {
            unquotedKeyMatches.forEach(match => {
                const keyMatch = match.match(/\{\s*([a-zA-Z_$][a-zA-Z0-9_$-]*)\s*:/);
                if (keyMatch && keyMatch[1]) {
                    const className = keyMatch[1].trim();
                    if (className && /^[a-zA-Z][a-zA-Z0-9_-]*$/.test(className)) {
                        classNames.add(className);
                    }
                }
            });
        }
        
        // 6. 处理数组语法中的字符串字面量
        const arrayStringMatches = cleanExpression.match(/\[([^\]]*)\]/g);
        if (arrayStringMatches) {
            arrayStringMatches.forEach(arrayMatch => {
                const arrayContent = arrayMatch.slice(1, -1);
                const stringInArray = arrayContent.match(/['"]([^'"]+)['"]/g);
                if (stringInArray) {
                    stringInArray.forEach(str => {
                        const className = str.slice(1, -1);
                        if (className && className.trim()) {
                            if (className.includes(' ')) {
                                className.split(/\s+/).forEach(cls => {
                                    if (cls.trim()) classNames.add(cls.trim());
                                });
                            } else {
                                classNames.add(className.trim());
                            }
                        }
                    });
                }
            });
        }
        
    } catch (error) {
        // 静默处理错误
    }
    
    return Array.from(classNames);
}

/**
 * 检测项目根目录
 * @param {string} startPath - 开始路径
 * @returns {string} 项目根目录路径
 */
export function detectProjectRoot(startPath = process.cwd()) {
    try {
        const fs = require('fs');
        const path = require('path');
        
        console.log(`[JZ UnoCSS] 开始检测项目根目录，起始路径: ${startPath}`);
        
        // 方法1: 使用相对路径向上查找（最简单可靠的方法）
        // 插件位于 uni_modules/jz-unocss-uvue/js/watchers/file-scanner.js
        // 需要向上4级找到项目根目录
        const currentFilePath = __filename || __dirname;
        console.log(`[JZ UnoCSS] 当前文件路径: ${currentFilePath}`);
        
        // 从当前文件位置向上查找
        let searchPath = currentFilePath;
        if (currentFilePath.includes('file-scanner.js')) {
            // 如果是从文件直接运行，向上4级: js/watchers/file-scanner.js -> js/watchers -> js -> jz-unocss-uvue -> uni_modules -> 项目根目录
            searchPath = path.resolve(path.dirname(currentFilePath), '../../../../');
        } else if (currentFilePath.includes('jz-unocss-uvue')) {
            // 如果是从插件目录运行，向上2级: uni_modules/jz-unocss-uvue -> uni_modules -> 项目根目录
            searchPath = path.resolve(currentFilePath, '../../');
        } else {
            // 使用相对路径从当前目录向上查找
            searchPath = path.resolve(process.cwd(), '../../');
        }
        
        console.log(`[JZ UnoCSS] 尝试相对路径检测: ${searchPath}`);
        
        if (fs.existsSync(searchPath)) {
            const hasManifest = fs.existsSync(path.join(searchPath, 'manifest.json'));
            const hasPages = fs.existsSync(path.join(searchPath, 'pages.json'));
            const hasUniModules = fs.existsSync(path.join(searchPath, 'uni_modules'));
            const hasPackageJson = fs.existsSync(path.join(searchPath, 'package.json'));
            
            console.log(`[JZ UnoCSS] 相对路径检测结果:`);
            console.log(`[JZ UnoCSS] - manifest.json: ${hasManifest}`);
            console.log(`[JZ UnoCSS] - pages.json: ${hasPages}`);
            console.log(`[JZ UnoCSS] - uni_modules: ${hasUniModules}`);
            console.log(`[JZ UnoCSS] - package.json: ${hasPackageJson}`);
            
            if (hasManifest || hasPages || hasUniModules || hasPackageJson) {
                console.log(`[JZ UnoCSS] ✅ 通过相对路径找到项目根目录: ${searchPath}`);
                return searchPath;
            }
        }
        
        // 方法2: 从当前路径向上逐级查找（备选方法）
        console.log(`[JZ UnoCSS] 相对路径方法失败，使用向上查找方法...`);
        let currentPath = startPath;
        let attempts = 0;
        const maxAttempts = 10;
        
        while (currentPath !== path.dirname(currentPath) && attempts < maxAttempts) {
            attempts++;
            
            const hasManifest = fs.existsSync(path.join(currentPath, 'manifest.json'));
            const hasPages = fs.existsSync(path.join(currentPath, 'pages.json'));
            const hasUniModules = fs.existsSync(path.join(currentPath, 'uni_modules'));
            const hasPackageJson = fs.existsSync(path.join(currentPath, 'package.json'));
            
            console.log(`[JZ UnoCSS] 向上查找 ${attempts}/${maxAttempts}: ${currentPath}`);
            console.log(`[JZ UnoCSS] - manifest.json: ${hasManifest}, pages.json: ${hasPages}, uni_modules: ${hasUniModules}`);
            
            if (hasManifest || hasPages || hasUniModules || hasPackageJson) {
                console.log(`[JZ UnoCSS] ✅ 向上查找找到项目根目录: ${currentPath}`);
                return currentPath;
            }
            
            currentPath = path.dirname(currentPath);
        }
        
        // 方法3: 使用当前工作目录作为最后备选
        console.log(`[JZ UnoCSS] 所有方法都失败，使用当前工作目录: ${process.cwd()}`);
        return process.cwd();
        
    } catch (error) {
        console.warn('[JZ UnoCSS] ❌ 检测项目根目录失败:', error.message);
        console.log(`[JZ UnoCSS] 🔄 使用当前工作目录: ${process.cwd()}`);
        return process.cwd();
    }
}

/**
 * 扫描项目文件
 * @param {string[]} extensions - 文件扩展名数组
 * @param {string} projectRoot - 项目根目录
 * @returns {string[]} 文件路径数组
 */
export function scanProjectFiles(extensions = ['.uvue'], projectRoot = null) {
    try {
        console.log(`[JZ UnoCSS] 📂 开始扫描项目文件...`);
        console.log(`[JZ UnoCSS] 🎯 目标扩展名: ${extensions.join(', ')}`);
        console.log(`[JZ UnoCSS] 📍 指定根目录: ${projectRoot || '未指定'}`);
        
        const realProjectRoot = projectRoot || detectProjectRoot();
        console.log(`[JZ UnoCSS] 🏠 实际项目根目录: ${realProjectRoot}`);
        
        const files = scanDirectory(realProjectRoot, extensions);
        
        console.log(`[JZ UnoCSS] ✅ 扫描完成，找到 ${files.length} 个文件`);
        
        if (files.length > 0) {
            console.log(`[JZ UnoCSS] 📋 文件列表:`);
            files.slice(0, 10).forEach((file, index) => {
                console.log(`[JZ UnoCSS]   ${index + 1}. ${file}`);
            });
            if (files.length > 10) {
                console.log(`[JZ UnoCSS]   ... 还有 ${files.length - 10} 个文件`);
            }
        } else {
            console.warn(`[JZ UnoCSS] ⚠️ 未找到任何 ${extensions.join(', ')} 文件`);
            console.log(`[JZ UnoCSS] 🔍 请检查项目根目录是否正确: ${realProjectRoot}`);
            
            // 列出根目录下的内容以供调试
            try {
                const fs = require('fs');
                const rootContents = fs.readdirSync(realProjectRoot);
                console.log(`[JZ UnoCSS] 📁 根目录内容: ${rootContents.join(', ')}`);
            } catch (error) {
                console.warn(`[JZ UnoCSS] 无法读取根目录内容:`, error.message);
            }
        }
        
        return files;
    } catch (error) {
        console.error('[JZ UnoCSS] ❌ 扫描项目文件失败:', error.message);
        console.error('[JZ UnoCSS] 错误堆栈:', error.stack);
        return [];
    }
}

/**
 * 从文件中提取类名
 * @param {string} filePath - 文件路径
 * @returns {string[]} 类名数组
 */
export function extractClassNamesFromFile(filePath) {
    try {
        const fs = require('fs');
        const content = fs.readFileSync(filePath, 'utf-8');
        return extractClassNamesFromContent(content);
    } catch (error) {
        console.warn(`[JZ UnoCSS] 读取文件失败 ${filePath}:`, error.message);
        return [];
    }
}

/**
 * 扫描项目并提取所有类名
 * @param {string[]} extensions - 文件扩展名数组
 * @param {string} projectRoot - 项目根目录
 * @returns {string[]} 类名数组
 */
export function scanAndExtractClassNames(extensions = ['.uvue'], projectRoot = null) {
    const allClassNames = new Set();
    const files = scanProjectFiles(extensions, projectRoot);
    
    for (const file of files) {
        const classNames = extractClassNamesFromFile(file);
        classNames.forEach(cls => allClassNames.add(cls));
    }
    
    return Array.from(allClassNames);
}

/**
 * 从文件代码中提取类名 (alias for extractClassNamesFromContent)
 * @param {string} code - 文件代码内容
 * @returns {string[]} 类名数组
 */
export function extractClassNamesFromCode(code) {
    return extractClassNamesFromContent(code);
}

// 函数已在定义时导出，无需重复导出 